package com.farm.wcp.client.utils;

import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.net.ssl.SSLContext;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONObject;

public class HttpUtils {
	private static final Logger log = Logger.getLogger(HttpUtils.class);

	public static JSONObject httpGet(String url) {
		return httpGet(url, new HashMap<String, String>());
	}

	// 是否跳过证书校验，默認進行校驗
	private static boolean IsPassSSLcheck = false;

	/**
	 * 是否跳过证书校验，默認進行校驗
	 * 
	 * @param isPassSSLcheck
	 */
	public static void setIsPassSSLcheck(boolean isPassSSLcheck) {
		IsPassSSLcheck = isPassSSLcheck;
	}

	public static JSONObject httpGet(String url, Map<String, String> headers) {
		log.info("*******http-Get:" + url);
		HttpGet httpGet = new HttpGet(url);
		CloseableHttpResponse response = null;
		CloseableHttpClient httpClient = IsPassSSLcheck ? getHttpClient(): HttpClients.createDefault() ;
		RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(5000).setConnectTimeout(5000).build();
		httpGet.setConfig(requestConfig);

		for (Map.Entry<String, String> node : headers.entrySet()) {
			httpGet.addHeader(node.getKey(), node.getValue());
		}

		try {
			response = httpClient.execute(httpGet, new BasicHttpContext());
			if (response.getStatusLine().getStatusCode() != 200) {
				JSONObject json = new JSONObject();
				json.put("MESSAGE",
						"request url failed, http code=" + response.getStatusLine().getStatusCode() + ", url=" + url);
				json.put("STATE", "1");
				log.error("*******API error:" + json.get("MESSAGE"));
			}
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				String resultStr = EntityUtils.toString(entity, "utf-8");
				log.info("*******http-result:" + resultStr);
				resultStr = resultStr.replace("callback(", "").replace(")", "").replace(";", "");
				if (resultStr.trim().indexOf("{") == 0) {
					JSONObject result = new JSONObject(resultStr);
					return result;
				}
				if (resultStr.trim().indexOf("[") == 0) {
					JSONArray array = new JSONArray(resultStr);
					JSONObject result = new JSONObject();
					result.put("array", array);
					result.put("size", array.length());
					return result;
				}
				JSONObject json = new JSONObject();
				json.put("MESSAGE", resultStr);
				json.put("STATE", "1");
				return json;
			} else {
				JSONObject json = new JSONObject();
				json.put("MESSAGE", "not exist response entity!");
				json.put("STATE", "1");
				log.info("*******http-result:" + json.toString());
				return json;
			}
		} catch (IOException e) {
			JSONObject json = new JSONObject();
			json.put("MESSAGE", e.getMessage());
			json.put("STATE", "1");
			log.error("*******http-result:" + json.toString());
			return json;
		} finally {
			if (httpClient != null) {
				try {
					httpClient.close();
				} catch (IOException e) {
					log.error("*******API error:" + "httpGet:" + e + e.getMessage());
				}
			}
			if (response != null) {
				try {
					response.close();
				} catch (IOException e) {
					log.error("*******API error:" + "httpGet:" + e + e.getMessage());
				}
			}
		}
	}

	public static JSONObject httpPost(String url, Map<String, String> data) {
		log.info("*******API load(httpPost):" + url);
		HttpPost httpPost = new HttpPost(url);
		CloseableHttpResponse response = null;
		CloseableHttpClient httpClient = HttpClients.createDefault();
		RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(5000).setConnectTimeout(5000).build();
		httpPost.setConfig(requestConfig);
		// httpPost.addHeader("Content-Type", "application/json");
		try {
			List<NameValuePair> params = new ArrayList<NameValuePair>();
			for (String key : data.keySet()) {
				params.add(new BasicNameValuePair(key, data.get(key)));
			}
			httpPost.setEntity(new UrlEncodedFormEntity(params, Consts.UTF_8));
			response = httpClient.execute(httpPost, new BasicHttpContext());
			if (response.getStatusLine().getStatusCode() != 200) {
				System.out.println(
						"request url failed, http code=" + response.getStatusLine().getStatusCode() + ", url=" + url);
				JSONObject json = new JSONObject();
				json.put("MESSAGE",
						"request url failed, http code=" + response.getStatusLine().getStatusCode() + ", url=" + url);
				json.put("STATE", "1");
				log.error("*******API error:" + json.get("MESSAGE"));
				return json;
			}
			HttpEntity entity = response.getEntity();
			if (entity != null) {
				String resultStr = EntityUtils.toString(entity, "utf-8");
				JSONObject result = new JSONObject(resultStr);
				return result;
			} else {
				JSONObject json = new JSONObject();
				json.put("MESSAGE", "not exist response entity!");
				json.put("STATE", "1");
				log.error("*******API error:" + json.get("MESSAGE"));
				return json;
			}
		} catch (IOException e) {
			System.out.println("request url=" + url + ", exception, msg=" + e.getMessage());
			JSONObject json = new JSONObject();
			json.put("MESSAGE", e.getMessage());
			json.put("STATE", "1");
			log.error("*******API error:" + json.get("MESSAGE"));
			return json;
		} finally {
			if (httpClient != null) {
				try {
					httpClient.close();
				} catch (IOException e) {
					System.out.println("httpGet:" + e + e.getMessage());
				}
			}
			if (response != null) {
				try {
					response.close();
				} catch (IOException e) {
					System.out.println("httpGet:" + e + e.getMessage());
				}
			}
		}
	}

//跳過證書校驗跳过证书校验
	private static CloseableHttpClient getHttpClient() {
		RegistryBuilder<ConnectionSocketFactory> registryBuilder = RegistryBuilder.<ConnectionSocketFactory>create();
		ConnectionSocketFactory plainSF = new PlainConnectionSocketFactory();
		registryBuilder.register("http", plainSF);
		// 指定信任密钥存储对象和连接套接字工厂
		try {
			KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
			// 信任任何链接
			TrustStrategy anyTrustStrategy = new TrustStrategy() {
				@Override
				public boolean isTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException {
					return true;
				}
			};
			SSLContext sslContext = SSLContexts.custom().useTLS().loadTrustMaterial(trustStore, anyTrustStrategy)
					.build();
			LayeredConnectionSocketFactory sslSF = new SSLConnectionSocketFactory(sslContext,
					SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
			registryBuilder.register("https", sslSF);
		} catch (KeyStoreException e) {
			throw new RuntimeException(e);
		} catch (KeyManagementException e) {
			throw new RuntimeException(e);
		} catch (NoSuchAlgorithmException e) {
			throw new RuntimeException(e);
		}
		Registry<ConnectionSocketFactory> registry = registryBuilder.build();
		// 设置连接管理器
		PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager(registry);
//        connManager.setDefaultConnectionConfig(connConfig);
//        connManager.setDefaultSocketConfig(socketConfig);
		// 构建客户端
		return HttpClientBuilder.create().setConnectionManager(connManager).build();
	}
}
